/*
 * cubeQueue.h
 *
 * A simple queue implementation used for the heuristic generator
 *
 *  Created on: Oct 6, 2013
 * @author Daniel Rogers
 */

#ifndef CUBEQUEUE_H_
#define CUBEQUEUE_H_

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

#include "cube.h"

//THIS CANNOT EXCEED (2^32)-1 unless changes are made to the Node struct
#ifndef CUBES_PER_NODE
//1024 cubes/node right now for compressed cubes
// since CUBES_PER_SET == 8
#define ITEMS_PER_NODE 128
#define CUBES_PER_NODE (ITEMS_PER_NODE * CUBES_PER_SET)
//#define ITEMS_PER_NODE 1024
//#define CUBES_PER_NODE ITEMS_PER_NODE
#endif

typedef struct Node Node;

//Internal queue struct
struct Node
{
    //The cube state at the node
    CompressedCubeSet cubes[ITEMS_PER_NODE];
    //Cube cubes[ITEMS_PER_NODE];
    //The layer the cube is on
    uint8_t layers[CUBES_PER_NODE];

    //Where in the array to put next cube
    uint32_t nxt_pos;
    //where in the array the storage starts
    uint32_t start_pos;

    //The next node in the queue
    Node * next;
}__attribute__((packed));

typedef struct Queue
{
    Node * head;
    Node * tail;
} Queue;

/*
 * Remove the item from the head of the queue
 *
 * @param q The queue to dequeue from
 *
 * @return The Cube state at the head of the queue
 */
Cube deq(Queue * q);

/*
 * Add an item to the tail of the queue
 *
 * @param[out] q A pointer to the Queue state to add a node to
 * @param cube The cube state to add to the queue
 */
void enq(Queue * q, Cube cube, uint8_t layer);

/*
 * initializes a queue
 * Must be called prior to queue use
 *
 * @param q A pointer to the queue to initialize
 */
void initQueue(Queue * q);

/*
 * Check if a queue is empty
 *
 * @param q The queue to check
 *
 * @return true if the queue is empty
 */
bool isEmpty(Queue * const q);

#endif /* CUBEQUEUE_H_ */
